package MTRequest;

import java.sql.ResultSet;
import java.util.ArrayList;

import MTProxyServer.MTConstant;
import MTProxyServer.MessageCentre;
import SQLManager.SQLManager;

/**
 * This class handle to synchronize the Server's DB with the User's local DB.
 * @author King
 *
 */
public class MTServerSynDataFromServerDB extends MTRequest {

	private int curIndex = 0;
	ArrayList< UpdateListContent > mUpdateList;
	
	public MTServerSynDataFromServerDB( MessageCentre aMSGCenter )
	{
		super( aMSGCenter );
		this.mRequestState = MTConstant.MT_REQ_NO_READY;
	}
	
	protected void ProcessReqest( int aPeerState, String peerRawData )
	{
		switch( aPeerState ){
			case MTConstant.MT_REQ_CSYN_DFSDB_UPDATE_REQUEST:{
				this.mReceivedFromPeerRawData.add( peerRawData );
				
				
				
				// Check Any Update
				// 
				//  Search for Server's DB.....
				mUpdateList = CheckUpdateList( peerRawData );
				
				System.out.println( "mUpdateList size: " + mUpdateList.size() );
				
				
				//
				//	Prepare all Update data
				//
				// Remark:
				// --Protocol Format--
				// Update Type ID, EventID, Master, ProductID, Owner, Product Name, Description, Price, Quality, Photo
				//
				//if( mUpdateList.size() > 0 ){
					for( int i = 0 ; i < mUpdateList.size() ; ++i ){
						switch( mUpdateList.get( i ).mUpdateType ){
							case MTConstant.MT_ID_UPT_CREATE_TABLE:{
								PrepareEventInfo( mUpdateList.get(i) );
								break;
							}
							case MTConstant.MT_ID_UPT_CREATE_PRODUCT:{
								PrepareProductInfo( mUpdateList.get(i) );
								break;
							}
							case MTConstant.MT_ID_UPT_STOCK_TAKE_EVENT:{
								PrepareDebtTable( mUpdateList.get(i) );
								break;
							}
						}
					}
					
				//}
				
				break;
			}
			case MTConstant.MT_REQ_CSYN_DFSDB_UPDATING_DB:
			case MTConstant.MT_REQ_CSYN_DFSDB_UPDATING_DB_LAST: {
				this.mReceivedFromPeerRawData.add( peerRawData );
				
				// Change the Previous Update Item' IsFinish to 'TRUE'
				// 
				// Event's Synchronize Table
				//
				//  ...
				//
				String userID = this.mReceivedFromPeerRawData.get( 0 );
				
				UpdateUserUpdateTable( userID, mUpdateList.get( curIndex ).mID );
				UpdateSynchronizeTable( userID, mUpdateList.get( curIndex ).mEventID );
				++curIndex;
				
				break;
			}
		}
	}
	
	protected void UpdateRequestState( int aPeerState )
	{
		if( MTConstant.MT_REQ_CSYN_DFSDB_UPDATE_REQUEST == aPeerState ){
			if( 0 != this.mSendingToPeerRawData.size() ){
				this.mRequestState = MTConstant.MT_REQ_SSYN_DFSDB_UPDATED_PRODUCT;
			}
			else{
				this.mRequestState = MTConstant.MT_REQ_SSYN_DFSDB_NO_UPDATED;
			}
		}
		else{	
			if( curIndex == this.mSendingToPeerRawData.size() - 1 ){
				this.mRequestState = MTConstant.MT_REQ_SSYN_DFSDB_UPDATED_PRODUCT_LAST;
			}
			else if( curIndex >= this.mSendingToPeerRawData.size() ){
				this.mRequestState = MTConstant.MT_REQ_FINISH;
			}
		}
	}
	
	public void SendRequest()
	{
		boolean isClosed = false;
		String request = "" + MTConstant.MT_REQID_SYNCHRONIZE_DATA_FROM_SERVER + MTConstant.MT_REQ_ITEM_SEPARATER
						+ this.mRequestState + MTConstant.MT_REQ_ITEM_SEPARATER;
		
		switch( this.mRequestState ){
			case MTConstant.MT_REQ_SSYN_DFSDB_NO_UPDATED:{
				request += " ";
				isClosed = true;
				break;
			}
			case MTConstant.MT_REQ_SSYN_DFSDB_UPDATED_PRODUCT:
			case MTConstant.MT_REQ_SSYN_DFSDB_UPDATED_PRODUCT_LAST:{
				request += this.mSendingToPeerRawData.get( curIndex );
				break;
			}
			case MTConstant.MT_REQ_FINISH:{
				this.Finish();
				return;
			}
		}
		this.SendMSG(request);
		
		if( isClosed ){
			this.Finish();
		}
	}
	
	private ArrayList< UpdateListContent > CheckUpdateList( String userID )
	{
		System.out.println( "----> CheckUpdateList() ");
		ArrayList< UpdateListContent > updateList = new ArrayList< UpdateListContent >();
		String userDB = "User_" + userID;
		
		SQLManager sqlManager = SQLManager.GetInstance();
		try{
			sqlManager.ConnectSQL();
			
			ResultSet rs = sqlManager.Query( 
					String.format(
					"SELECT * FROM " + MTConstant.MT_SQL_DB + ".%s_UpdateTable " +
					"where IsFinished = 0 order by TimeCreated", userDB ) 
					, "" );
			
			while( rs.next() ){
				updateList.add( 
						new UpdateListContent(
								rs.getString( "ID" ),
								rs.getString( "EventID" ),
								rs.getString( "Master" ),
								rs.getString( "Content" ),
								rs.getInt( "UpdateType" ) )
				);
				System.out.println( "ID: " + rs.getString( "ID" ));
				System.out.println( "EventID: " + rs.getString( "EventID" ));
				System.out.println( "Master: " + rs.getString( "Master" ));
				System.out.println( "Content: " + rs.getString( "Content" ));
				System.out.println( "UpdateType: " + rs.getInt( "UpdateType" ));
				System.out.println( "IsFinished: " + rs.getString( "IsFinished" ));
				System.out.println( "TimeCreated: " + rs.getString( "TimeCreated" ));
			}
			sqlManager.Close();
		}
		catch( Exception e ){
			e.printStackTrace();
		}
		
		System.out.println( "<---- CheckUpdateList() ");
		return updateList;
	}
	
	private void PrepareEventInfo( UpdateListContent aUpdateListItem )
	{
		SQLManager sqlManager = SQLManager.GetInstance();
		try{
			sqlManager.ConnectSQL( );
			
			ResultSet rs = sqlManager.Query( 
					String.format(
					"SELECT * FROM " + MTConstant.MT_SQL_DB + ".EventTable " +
					"where EventID = %s", aUpdateListItem.mEventID ) 
					, "" );
			
			if( rs.next() ){
				this.mSendingToPeerRawData.add(
						"" + aUpdateListItem.mUpdateType + MTConstant.MT_REQ_RAW_DATA_SEPARATER +
						rs.getString( "EventID" ) + MTConstant.MT_REQ_RAW_DATA_SEPARATER +
						rs.getString( "Master" ) + MTConstant.MT_REQ_RAW_DATA_SEPARATER +
						rs.getString( "Title" ) + MTConstant.MT_REQ_RAW_DATA_SEPARATER +
						rs.getString( "ContactMember" ) + MTConstant.MT_REQ_RAW_DATA_SEPARATER +
						rs.getString( "Location" ) );	
				System.out.println( "EventID: " + rs.getString( "EventID" ));
				System.out.println( "Master: " + rs.getString( "Master" ));
				System.out.println( "Title: " + rs.getString( "Title" ));
				System.out.println( "ContactMember: " + rs.getString( "ContactMember" ));
				System.out.println( "Location: " + rs.getString( "Location" ));
			}
			sqlManager.Close();
		}
		catch( Exception e ){
			e.printStackTrace();
		}
	}

	private void PrepareProductInfo( UpdateListContent aUpdateListItem )
	{
		SQLManager sqlManager = SQLManager.GetInstance();
		try{
			sqlManager.ConnectSQL(  );
			
			ResultSet rs = sqlManager.Query( 
					String.format(
					"SELECT * FROM " + MTConstant.MT_SQL_DB + ".ProductList_%s " +
					"where ProductID = %s" 
					,aUpdateListItem.mEventID
					,aUpdateListItem.mCoentent )
					, "" );
			
			if( rs.next() ){
				this.mSendingToPeerRawData.add(
						"" + aUpdateListItem.mUpdateType + MTConstant.MT_REQ_RAW_DATA_SEPARATER +
						aUpdateListItem.mEventID + MTConstant.MT_REQ_RAW_DATA_SEPARATER +
						rs.getString( "ProductID" ) + MTConstant.MT_REQ_RAW_DATA_SEPARATER +
						rs.getString( "Owner" ) + MTConstant.MT_REQ_RAW_DATA_SEPARATER +
						rs.getString( "ProductName" ) + MTConstant.MT_REQ_RAW_DATA_SEPARATER +
						rs.getString( "Description" ) + MTConstant.MT_REQ_RAW_DATA_SEPARATER +
						rs.getString( "Price" ) + MTConstant.MT_REQ_RAW_DATA_SEPARATER + 
						rs.getString( "Quality" ) + MTConstant.MT_REQ_RAW_DATA_SEPARATER + 
						rs.getString( "Image" ) );	
				System.out.println( "ProductID: " + rs.getString( "ProductID" ));
				System.out.println( "Owner: " + rs.getString( "Owner" ));
				System.out.println( "ProductName: " + rs.getString( "ProductName" ));
				System.out.println( "Description: " + rs.getString( "Description" ));
				System.out.println( "Price: " + rs.getString( "Price" ));
				System.out.println( "Quality: " + rs.getString( "Quality" ));
				System.out.println( "Image: " + rs.getString( "Image" ));
			}
			sqlManager.Close();
		}
		catch( Exception e ){
			e.printStackTrace();
		}
	}
	
	private void PrepareDebtTable( UpdateListContent aUpdateListItem )
	{
		String sendingRawData = "" + aUpdateListItem.mUpdateType + MTConstant.MT_REQ_RAW_DATA_SEPARATER +
					aUpdateListItem.mEventID + MTConstant.MT_REQ_RAW_DATA_SEPARATER;
		SQLManager sqlManager = SQLManager.GetInstance();
		try{
			sqlManager.ConnectSQL();
			
			ResultSet rs = sqlManager.Query( 
					String.format(
					"SELECT * FROM " + MTConstant.MT_SQL_DB + ".DebtTable_%s "
					,aUpdateListItem.mEventID )
					, "" );
			
			while( rs.next() ){
				sendingRawData += rs.getString( "Renter" ) + MTConstant.MT_REQ_RAW_DATA_SEPARATER;
				sendingRawData += rs.getString( "Debtor" ) + MTConstant.MT_REQ_RAW_DATA_SEPARATER;
				sendingRawData += rs.getString( "Money" ) ;
				
				if( !rs.isLast() ){
					sendingRawData += MTConstant.MT_REQ_RAW_DATA_SEPARATER;
				}
				
				System.out.println( "Renter: " + rs.getString( "Renter" ));
				System.out.println( "Debtor: " + rs.getString( "Debtor" ));
				System.out.println( "Money: " + rs.getString( "Money" ));
			}
			sqlManager.Close();
		}
		catch( Exception e ){
			e.printStackTrace();
		}
		
		this.mSendingToPeerRawData.add( sendingRawData );
	}
	
	private void UpdateUserUpdateTable( String aUserID, String aUpdateID )
	{
		String userDB = "User_" + aUserID;
		SQLManager sqlManager = SQLManager.GetInstance();
		try{
			sqlManager.ConnectSQL();
			String query = String.format(
					"UPDATE " + MTConstant.MT_SQL_DB + ".%s_UpdateTable SET IsFinished = 1 WHERE ID = %s"
					, userDB
					, aUpdateID );
			sqlManager.UpdateTable( query );
			
			sqlManager.Close();
		}
		catch( Exception e ){
			e.printStackTrace();
		}
	}
	
	private void UpdateSynchronizeTable( String aUserID, String aEventID )
	{
		SQLManager sqlManager = SQLManager.GetInstance();
		try{
			sqlManager.ConnectSQL( );
			
			String query = String.format(
					"SELECT UpdateCount From " + MTConstant.MT_SQL_DB + ".SynchronizeTable_%s WHERE UserID = %s"
					, aEventID
					, aUserID );
			ResultSet rs = sqlManager.Query( query , "" );
			
			
			int updateCount = 0;
			if( rs.next() ){
				updateCount = rs.getInt( 1 );
			}
			System.out.println( "UpdateCount: " + updateCount );
			System.out.println( "EventID : " + aEventID );
			System.out.println( "UserID : " + aUserID );
			
			--updateCount;
			query = String.format(
					"UPDATE " + MTConstant.MT_SQL_DB + ".SynchronizeTable_%s SET UpdateCount = %d WHERE UserID = %s"
					, aEventID
					, updateCount
					, aUserID );
			sqlManager.UpdateTable( query );
			
			if( 0 == updateCount ){
				query = String.format(
						"UPDATE " + MTConstant.MT_SQL_DB + ".SynchronizeTable_%s SET IsUpdated = true WHERE UserID = %s"
						, aEventID
						, aUserID );
				sqlManager.UpdateTable( query );
			}
			
			sqlManager.Close();
		}
		catch( Exception e ){
			e.printStackTrace();
		}
	}
}

class UpdateListContent
{
	UpdateListContent( String aID, String aEventID, String aMaster, String aContent, int aUpdateType )
	{
		mID = aID;
		mEventID = aEventID;
		mMaster = aMaster;
		mCoentent = aContent;
		mUpdateType = aUpdateType;
	}
	
	public String mID;
	public String mEventID;
	public String mMaster;
	public String mCoentent;
	public int mUpdateType;
}